package org.eli;

public class Camera {

    // 相机位置
    private Vec3 origin;

    // 左下角
    private Vec3 lowerLeftCorner;

    // 水平
    private Vec3 horizontal;

    // 垂直
    private Vec3 vertical;

    // z
    private Vec3 u;

    // x
    private Vec3 w;

    // y
    private Vec3 v;

    // 透镜半径
    private double lensRadius;

    /**
     * 相机
     *
     * @param lookfrom      相机位置
     * @param lookat        观察点
     * @param vup           相机的倾斜方向 view up
     * @param vfov          角度 field of view
     * @param aspect        宽高比
     * @param aperture      透镜直径
     * @param focusDist     重点区域
     */
    public Camera(Vec3 lookfrom, Vec3 lookat, Vec3 vup, double vfov, double aspect, double aperture, double focusDist) {
        origin = lookfrom;
        lensRadius = aperture / 2;

        double theta = RtWeekend.degreesToRadians(vfov);
        double halfHeight = Math.tan(theta / 2);
        double halfWidth = aspect * halfHeight;

        w = Main.unitVector(lookfrom.subtract(lookat));
        u = Main.unitVector(vup.cross(w));
        v = w.cross(u);

        lowerLeftCorner = origin.subtract(u.scale(halfWidth * focusDist)).subtract(v.scale(halfHeight * focusDist)).subtract(w.scale(focusDist));
        horizontal = u.scale(2 * halfWidth * focusDist);
        vertical = v.scale(2 * halfHeight * focusDist);
    }

    public Ray getRay(double u, double v) {
        Vec3 rd = Vec3.randomInUnitDisk().scale(lensRadius);
        double offset = rd.x() * u + rd.y() * v;

        return new Ray(origin.add(offset), lowerLeftCorner.add(horizontal.scale(u)).add(vertical.scale(v)).subtract(origin).subtract(offset));
    }
}
